<?php

namespace plugin\ycMassage\app\model;

use app\common\manager\SettingsMgr;
use Exception;
use plugin\ycMassage\utils\enum\CouponCodeState;
use plugin\ycMassage\utils\enum\NoticeType;
use plugin\ycMassage\utils\enum\OrdersState;
use plugin\ycMassage\utils\enum\OrdersType;
use plugin\ycMassage\utils\enum\PayType;
use plugin\ycMassage\utils\enum\ServiceState;
use plugin\ycMassage\utils\notice\Notice;
use think\facade\Db;
use think\facade\Env;
use WePay\Refund as WeChatRefund;

class MassageOrders extends Model
{
    protected $json = ['coupons'];
    protected $jsonAssoc = true;
    public static function complete($trade)
    {
        Db::startTrans();
        try {
            $Order = self::where(['trade' => $trade])->lock(true)->find();
            if ($Order) {
                if (!in_array($Order->state, [OrdersState::NOT_PAY['value'], OrdersState::PAY['value']])) {
                    throw new Exception('请勿重复完成订单');
                }
                $NotifyModel = null;
                switch ($Order->pay_type) {
                    case 'alipay':
                        break;
                    case 'wxpay':
                        $NotifyModel = MassageNotifyWechat::where(['out_trade_no' => $Order->trade])->find();
                        break;
                    case 'epay':
                        $NotifyModel = MassageNotifyEpay::where(['out_trade_no' => $Order->trade])->find();
                        break;
                }
                switch ($Order->orders_type) {
                    case OrdersType::RESERVATION['value']:
                        $start_time='';
                        $OrdersSub = MassageOrdersSub::where(['orders_id' => $Order->id])->select();
                        foreach ($OrdersSub as $item) {
                            $item->state = OrdersState::WAIT_START['value'];
                            $item->save();
                            $MassageAppointmentService = MassageAppointmentService::where(['orders_sub_id' => $item->id])->find();
                            if (!$MassageAppointmentService) {
                                throw new Exception('预约服务不存在');
                            }
                            if(!$start_time){
                                $start_time=$MassageAppointmentService->start_time;
                            }
                            if($Order->to_shop){
                                $MassageAppointmentService->state = ServiceState::ARRIVAL['value'];
                                $MassageAppointmentService->departure_time = date('Y-m-d H:i:s');
                                $MassageAppointmentService->arrival_time = date('Y-m-d H:i:s');
                            }else{
                                $MassageAppointmentService->state = ServiceState::WAIT_START['value'];
                            }
                            $MassageAppointmentService->save();
                            $MassageService = MassageService::where(['id' => $item->service_id])->find();
                            $MassageService->sales_num = Db::raw("sales_num+{$item->num}");
                            $MassageService->save();
                        }
                        $Order->state = OrdersState::WAIT_START['value'];
                        $Order->save();
                        if ($NotifyModel) {
                            $NotifyModel->state = 1;
                            $NotifyModel->save();
                        }
                            $notice = new Notice();
                            if($Order->to_shop){
                                $MassageUser=MassageUser::where(['id'=>$Order->uid])->find();
                                $name="{$MassageUser->nickname}({$MassageUser->mobile})";
                            }else{
                                $MassageOrdersAddress = MassageOrdersAddress::where(['orders_id' => $Order->id])->find();
                                $name="{$MassageOrdersAddress['name']}({$MassageOrdersAddress['mobile']})";
                                $notice->addUSER($MassageOrdersAddress->mobile, null);
                            }
                            $MassageUserWechat=MassageUserWechat::where(['uid'=>$Order->uid])->find();
                            if ($MassageUserWechat) {
                                $notice->addUSER(null, $MassageUserWechat->openid);
                            }
                            $MassageUserT = MassageUser::alias('u')->where(['u.id' => $Order->alias_id])
                                ->join('MassageUserWechat uw', 'uw.uid=u.id', 'left')
                                ->field('u.nickname,u.mobile,uw.openid')
                                ->find();
                            if ($MassageUserT) {
                                $Order->title="{$MassageUserT->nickname}({$MassageUserT->mobile})";
                                $notice->addTECHNICIAN($MassageUserT->mobile, $MassageUserT->openid);
                            }
                            $notice->saas_appid = $Order->saas_appid;
                            $notice->type = NoticeType::ORDERS_PAY['value'];
                            $notice->setData([
                                'title' => $Order->title,
                                'trade' => $Order->trade,
                                'name' => $name,
                                'price' => $Order->price,
                                'time' => $start_time,
                                'create_time' => $Order->create_time,
                            ]);
                            $notice->send();
                        Db::commit();
                        return true;
                    case OrdersType::OVERTIME['value']:
                        $OrdersSub = MassageOrdersSub::where(['orders_id' => $Order->id])->select();
                        foreach ($OrdersSub as $item) {
                            $item->state = OrdersState::SERVICE_ING['value'];
                            $item->save();
                            $MassageAppointmentService = MassageAppointmentService::where([
                                'id' => $item->appointment_service_id, 'uid' => $Order->uid
                            ])->find();
                            if (!$MassageAppointmentService) {
                                throw new Exception('预约服务不存在');
                            }
                            $MassageService = MassageService::where(['id' => $item->service_id])->find();
                            if ($MassageService->overtime_separate) {
                                $duration = $MassageService->overtime_duration * $item->num;
                            } else {
                                $duration = $MassageService->service_duration * $item->num;
                            }
                            $MassageAppointmentService->duration = Db::raw("duration+{$duration}");
                            $MassageAppointmentService->save();
                            $MassageService->sales_num = Db::raw("sales_num+{$item->num}");
                            $MassageService->save();
                        }
                        $Order->state = OrdersState::SERVICE_ING['value'];
                        $Order->save();
                        if ($NotifyModel) {
                            $NotifyModel->state = 1;
                            $NotifyModel->save();
                        }
                        $MassageOrdersAddress = MassageOrdersAddress::where(['orders_id' => $Order->id])->find();
                        $name="{$MassageOrdersAddress['name']}({$MassageOrdersAddress['mobile']})";
                        $notice = new Notice();
                        $notice->addUSER($MassageOrdersAddress->mobile, null);
                        $MassageUserWechat=MassageUserWechat::where(['uid'=>$Order->uid])->find();
                        if ($MassageUserWechat) {
                            $notice->addUSER(null, $MassageUserWechat->openid);
                        }
                        $MassageUserT = MassageUser::alias('u')->where(['u.id' => $Order->alias_id])
                            ->join('MassageUserWechat uw', 'uw.uid=u.id', 'left')
                            ->field('u.mobile,uw.openid')
                            ->find();
                        if ($MassageUserT) {
                            $notice->addTECHNICIAN($MassageUserT->mobile, $MassageUserT->openid);
                        }
                        $notice->saas_appid = $Order->saas_appid;
                        $notice->type = NoticeType::ORDERS_PAY['value'];
                        $notice->setData([
                            'title' => $Order->title,
                            'trade' => $Order->trade,
                            'name' => $name,
                            'price' => $Order->price,
                            'time' => $Order->pay_time,
                            'create_time' => $Order->create_time,
                        ]);
                        $notice->send();
                        Db::commit();
                        return true;
                    case OrdersType::MONEY['value']:
                        $moeny = $Order->price + $Order->give_price;
                        MassageUserBill::increase($Order->title, $Order->uid, $moeny);
                        $Order->state = OrdersState::FINISH['value'];
                        $Order->finish_time = date('Y-m-d H:i:s');
                        $Order->save();
                        if ($NotifyModel) {
                            $NotifyModel->state = 1;
                            $NotifyModel->save();
                        }
                        Db::commit();
                        return true;
                    case OrdersType::DEALER_APPLY['value']:
                        $MassageUserDealer = new MassageUserDealer;
                        $MassageUserDealer->uid = $Order->uid;
                        $MassageUserDealer->saas_appid = $Order->saas_appid;
                        $MassageUserDealer->orders_trade = $Order->trade;
                        $MassageUserDealer->orders_id = $Order->id;
                        $MassageUserDealer->apply_price = $Order->price;
                        $apply = getHpConfig('apply', $Order->saas_appid, 'dealer');
                        if ($apply == 'no') {
                            $MassageUserDealer->state = 1;
                        } else {
                            $MassageUserDealer->state = 0;
                        }
                        $MassageUserDealer->save();
                        $Order->state = OrdersState::FINISH['value'];
                        $Order->finish_time = date('Y-m-d H:i:s');
                        $Order->save();
                        if ($NotifyModel) {
                            $NotifyModel->state = 1;
                            $NotifyModel->save();
                        }
                        Db::commit();
                        return true;
                    default:
                        throw new Exception('订单类型不正确');
                }
            }
            throw new Exception('订单不存在');
        } catch (\Throwable $th) {
            Db::rollback();
            throw new Exception($th->getMessage());
        }
    }
    public static function cancel($trade)
    {
        Db::startTrans();
        try {
            $Order = self::where(['trade' => $trade, 'state' => OrdersState::NOT_PAY['value']])->lock(true)->find();
            if ($Order) {
                $Order->state = OrdersState::CANCEL['value'];
                $Order->cancel_time = date('Y-m-d H:i:s');
                $Order->save();
                switch ($Order->orders_type) {
                    case OrdersType::RESERVATION['value']:
                        $OrdersSub = MassageOrdersSub::where(['orders_id' => $Order->id])->select();
                        $scheduling_id = null;
                        foreach ($OrdersSub as $item) {
                            $item->state = OrdersState::CANCEL['value'];
                            $item->save();
                            $MassageAppointmentService = MassageAppointmentService::where(['orders_sub_id' => $item->id])->find();
                            if ($MassageAppointmentService) {
                                $scheduling_id = $MassageAppointmentService->scheduling_id;
                                $MassageAppointmentService->delete();
                            }
                        }
                        if ($scheduling_id) {
                            $MassageUserTechnicianScheduling = MassageUserTechnicianScheduling::where(['id' => $scheduling_id])->find();
                            if (!$MassageUserTechnicianScheduling) {
                                throw new \Exception('排班不存在', 1003);
                            }
                            $MassageUserTechnicianScheduling->appointment_time = MassageUserTechnicianScheduling::getNextAppointmentTime($MassageUserTechnicianScheduling, 0);
                            $MassageUserTechnicianScheduling->save();
                        }
                        break;
                }
                if($Order->coupons){
                    $useMassageCouponCode = MassageCouponCode::whereIn('id', $Order->coupons)->select();
                    foreach ($useMassageCouponCode as $item) {
                        $item->state = CouponCodeState::YES['value'];
                        $item->use_time = null;
                        $item->save();
                        $MassageCoupon = MassageCoupon::where(['id' => $item->coupon_id])->find();
                        if ($MassageCoupon) {
                            $MassageCoupon->use_num = Db::raw('use_num-1');
                            $MassageCoupon->save();
                        }
                    }
                }
                Db::commit();
                return true;
            }
            throw new Exception('订单不存在');
        } catch (\Throwable $th) {
            Db::rollback();
            throw new Exception($th->getMessage());
        }
    }
    public static function refund($orders_id, $MassageOrdersRefund=null, $charging = [])
    {
        $model = self::where(['id' => $orders_id])->find();
        $model->state = OrdersState::REFUND['value'];
        $model->save();
        $money = 0;
        if (!empty($charging['money'])) {
            $money = $charging['money'];
        }
        $modelSub = MassageOrdersSub::where(['orders_id' => $orders_id])
            ->whereIn('state', [OrdersState::PAY['value'], OrdersState::WAIT_START['value'], OrdersState::SERVICE_ING['value']])->select();
        $subMoney = 0;
        switch ($model->orders_type) {
            case OrdersType::RESERVATION['value']:
                foreach ($modelSub as $item) {
                    $item->state = OrdersState::REFUND['value'];
                    $item->save();
                    $MassageAppointmentService = MassageAppointmentService::where(['orders_sub_id' => $item->id])->find();
                    if (!$MassageAppointmentService) {
                        throw new Exception('预约服务不存在');
                    }
                    $MassageAppointmentService->delete();
                    $subMoney += $item->price;
                }
                $overtimeOrder = MassageOrders::where(['orders_id' => $model->id])->select();
                if ($overtimeOrder) {
                    foreach ($overtimeOrder as $item) {
                        $item->state = OrdersState::REFUND['value'];
                        $item->save();
                        $overtimeSub = MassageOrdersSub::where(['orders_id' => $item->id])
                            ->whereIn('state', [OrdersState::PAY['value'], OrdersState::WAIT_START['value'], OrdersState::SERVICE_ING['value']])->select();
                        foreach ($overtimeSub as $overtimeItem) {
                            $overtimeItem->state = OrdersState::REFUND['value'];
                            $overtimeItem->save();
                            $subMoney += $overtimeItem->price;
                        }
                    }
                }
                break;
            case OrdersType::OVERTIME['value']:
                foreach ($modelSub as $item) {
                    $item->state = OrdersState::REFUND['value'];
                    $item->save();
                    $MassageAppointmentService = MassageAppointmentService::where(['id' => $item->appointment_service_id, 'uid' => $model->uid])->find();
                    if (!$MassageAppointmentService) {
                        throw new Exception('预约服务不存在');
                    }
                    $MassageService = MassageService::where(['id' => $item->service_id])->find();
                    if ($MassageService->overtime_separate) {
                        $duration = $MassageService->overtime_duration * $item->num;
                    } else {
                        $duration = $MassageService->service_duration * $item->num;
                    }
                    $MassageAppointmentService->duration = Db::raw("duration-{$duration}");
                    $MassageAppointmentService->save();
                    $subMoney += $item->price;
                }
                break;
        }
        if ($money <= 0) {
            $money = $subMoney;
            if (isset($charging['service'])) {
                $service_price = $money * $charging['service'];
                if ($service_price > 0) {
                    $money = $service_price;
                }
            }
            $travel_price = $model->travel_price;
            if (isset($charging['travel'])) {
                $travel_price = $model->travel_price * $charging['travel'];
            }
            $money += $travel_price;
        }
        if ($money > 0) {
            if($MassageOrdersRefund){
                $MassageOrdersRefund->price = $money;
            }
            switch ($model->pay_type) {
                case PayType::WXPAY['value']:
                    # 微信退款开始
                    $NotifyModel = MassageNotifyWechat::where(['out_trade_no' => $model->trade])->find();
                    if (!$NotifyModel) {
                        throw new \Exception("订单支付记录不存在");
                    }
                    $_config = SettingsMgr::getChildren((int)$model->saas_appid, 'pay');
                    if (empty($_config['wxpay_state'])) {
                        throw new \Exception("未开启微信支付");
                    }
                    if (empty($_config['wxpay_mch_id']) || empty($_config['wxpay_mch_key']) || empty($_config['wxpay_ssl_key']) || empty($_config['wxpay_ssl_cer'])) {
                        throw new \Exception("未配置微信支付");
                    }
                    $config = [
                        // 缓存目录配置（可选，需拥有读写权限）
                        'cache_path'     => runtime_path('wxpay'),
                    ];
                    $config = array_merge($config, [
                        'appid' => $NotifyModel->appid,
                        'mch_id' => $_config['wxpay_mch_id'],
                        'mch_key' => $_config['wxpay_mch_key'],
                        'ssl_key'        => $_config['wxpay_ssl_key'],
                        'ssl_cer'        => $_config['wxpay_ssl_cer']
                    ]);
                    if (!empty($charging['refund_desc'])) {
                        $config['refund_desc'] = $charging['refund_desc'];
                    }

                    // 创建接口实例
                    $wechat = new WeChatRefund($config);
                    $domain = getHpConfig('domain', (int)$model->saas_appid, 'plugins_domains');
                    // 组装参数，可以参考官方商户文档
                    $options = [
                        'transaction_id'   => $NotifyModel->transaction_id,
                        'out_refund_no' => $model->trade,
                        'total_fee' => $NotifyModel->total_fee,
                        'refund_fee' => Env::get('APP_MODE') == 'dev' ? 1 : $money  * 10 *10,
                        'notify_url' => $domain . '/app/ycMassage/notify/wechatRefund',
                    ];
                    // 尝试创建订单
                    $result = $wechat->create($options);
                    if ($result['return_code'] !== 'SUCCESS') {
                        throw new \Exception($result['return_msg']);
                    }
                    if ($result['result_code'] !== 'SUCCESS') {
                        throw new \Exception($result['err_code'] . ':' . $result['err_code_des']);
                    }
                    break;
                case PayType::ALIPAY['value']:
                    break;
                case PayType::EPAY['value']:
                    MassageUserBill::increase("订单退款{$model->trade}", $model->uid, $money);
                    break;
                case PayType::MONEY['value']:
                    MassageUserBill::increase("订单退款{$model->trade}", $model->uid, $money);
                    break;
            }
        }
    }
}
